from common.quest import QuestStatus, Quest
from utils.db import DBSession
from utils.event_bus import EVENT_BUS


class QuestBook:
    """任务手册"""

    __slots__ = ('finished', 'in_process', 'accessible')

    def __init__(self):
        self.finished = set()
        self.in_process = set()
        self.accessible = set()

        for quest in DBSession.quests.values():
            if quest.status == QuestStatus.Accessible:
                self.accessible.add(quest.name)

    def __json__(self):
        return {
            'finished': list(self.finished),
            'in_process': {key: DBSession.quests.get(key).ok for key in self.in_process},
            'accessible': list(self.accessible)
        }

    def load(self, data: dict):
        self.accessible.update(data['accessible'])

        for quest_key in data['finished']:
            quest: Quest = DBSession.quests.get(quest_key)
            quest.status = QuestStatus.Finished
            self.finished.add(quest_key)
            self.accessible.discard(quest_key)

        for quest_key, ok_status in data['in_process'].items():
            quest: Quest = DBSession.quests.get(quest_key)
            quest.status = QuestStatus.InProcess
            quest.ok = ok_status
            self.in_process.add(quest_key)
            self.accessible.discard(quest_key)
            EVENT_BUS.player_interaction.register(quest.player_interaction)

    @property
    def title(self):
        text = f'任务'
        if self.accessible:
            text += f' ({len(self.accessible)})'

        return text

    def update(self):
        old = len(self.accessible)
        for quest_key, quest in DBSession.quests.items():
            if quest_key in self.finished or quest_key in self.in_process or quest_key in self.accessible:
                continue

            if quest.requirement is None:
                continue

            can_accept = True
            for key, value in quest.requirement.items():
                if key == 'quest':
                    if value not in self.finished:
                        can_accept = False
                        break

            if can_accept:
                self.accessible.add(quest_key)

        return old != len(self.accessible)
